package pers.vic.boot.security.redis;

import java.time.Duration;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import pers.vic.boot.security.autoconfigure.SecurityProperties;

@Configuration
@ConditionalOnExpression("${auth.redis.enabled:true}")
@ConfigurationProperties(prefix = SecurityProperties.SECURITY_PREFIX)
public class RedisConfig {

	/**
	 * 使用Lettuce 连接池的方式
	 * @param connectionFactory
	 * @return
	 */
	@Bean("redisTemplateCustomize")
	public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
		// 配置redisTemplate
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(connectionFactory);
		// key序列化
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		// value序列化
		redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
		redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
		redisTemplate.afterPropertiesSet();
		return redisTemplate;
	}

	/**
	 * 
	 * /** 缓存配置管理器
	 */
	@Bean
	@ConditionalOnMissingBean
	public CacheManager cacheManager(LettuceConnectionFactory factory) {
		// 以锁写入的方式创建RedisCacheWriter对象
		RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
		// 创建默认缓存配置对象
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofDays(1))
				.serializeKeysWith(
						RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
				.serializeValuesWith(RedisSerializationContext.SerializationPair
						.fromSerializer(new GenericJackson2JsonRedisSerializer()))
				.disableCachingNullValues();
		RedisCacheManager cacheManager = new RedisCacheManager(writer, config);
		return cacheManager;
	}

	/**
	 * redisService
	 */
	@Bean
	@ConditionalOnMissingBean
	public RedisService redisService(@Qualifier("redisTemplateCustomize")RedisTemplate<String, Object> redisTemplate) {
		return new RedisService(redisTemplate);
	}

}